import dpcDBs as dbs
from random import gauss, randint, seed

from numpy import linspace

def intLinSpace( start, stop, num ):
  vals = linspace( start, stop, num );
  for v in vals:
    v = round( v );

  return vals

class interpolate:
  def fixVotes( self, vote ):
    gtIndex = [i for i, v in enumerate( vote ) if v > 10]
    ltIndex = [i for i, v in enumerate( vote ) if v < 1]

    for i in gtIndex:
      while vote[i] > 10:
        vote[i] -= 1
        self.numDecremented += 1

    for i in ltIndex:
      while vote[i] < 1:
        vote[i] += 1
        self.numIncremented += 1

    self.numIncremented = int( self.numIncremented )
    self.numDecremented = int( self.numDecremented )
    return vote


  def genVotes( self, score, numVotes, scoreSum ):
    m = float( scoreSum ) / float( numVotes )
    s = 1.5

    # NEW VOTES ONLY
    if numVotes > 0:
      vote = self.fixVotes( [round( gauss( m, s ) ) for i in range( numVotes )] )


      # Adjust the individual votes to achieve the correct average
      while True:
        voteSum = sum( vote )

        # Sum is fine, so pass
        if voteSum == scoreSum:
          break


        if scoreSum < ( numVotes * 1 ):
          self.numDecremented += voteSum - scoreSum
          break

        if scoreSum > ( numVotes * 10 ):
          self.numIncremented += scoreSum - voteSum
          break


        i = randint( 0, len( vote ) - 1 )

        if voteSum > scoreSum and vote[i] > 1:
          vote[i] -= 1
        elif voteSum < scoreSum and vote[i] < 10:
          vote[i] += 1


      # Generate all the other things
      votes = intLinSpace( self.last.votes, score.votes, numVotes )
      views = intLinSpace( self.last.views, score.views, numVotes )
      comments = intLinSpace( self.last.comments, score.comments, numVotes )
      favourites = intLinSpace( self.last.favourites, score.favourites, numVotes )
      wishList = intLinSpace( self.last.wishList, score.wishList, numVotes )
      votes[-1] = score.votes
      views[-1] = score.views
      comments[-1] = score.comments
      favourites[-1] = score.favourites
      wishList[-1] = score.wishList


      # Append the new votes to the list
      for i, v in enumerate( vote ):
        v = dbs.voteVal( vote = v,
                         votes = votes[i],
                         views = views[i],
                         comments = comments[i],
                         favourites = favourites[i],
                         wishList = wishList[i] )
        self.genScores.append( v )



  def doInterpolation( self ):
    seed( self.challengeID )
    self.toIncrease = 0
    self.toDecrease = 0

    # Do the interpolation
    for i, score in enumerate( self.scores ):
      if i == 18:
        pass
      # If this and the next have the same vote count progress to the next
      if i + 1 < len( self.scores ) and self.scores[i + 1].votes == score.votes:
        continue

      # Compute num needed to compute
      numVotes = score.votes - self.last.votes
      scoreSum = round( score.votes * score.score - self.last.votes * self.last.score )

      # Gen votes and set the new last
      if numVotes:
        self.genVotes( score, numVotes, scoreSum )
        self.last = score

    # Fix the votes according to numIncr and numDecr
    numScores = len( self.genScores )
    for i in range( self.numIncremented ):
      pos = 0
      while True:
        pos = randint( 0, numScores )
        if self.genScores[pos].vote > 1:
          break
      self.genScores[pos].vote -= 1

    for i in range( self.numDecremented ):
      pos = 0
      while True:
        pos = randint( 0, numScores )
        if self.genScores[pos].vote < 10:
          break
      self.genScores[pos].vote += 1


    # Now do the scores
    for i in range( len( self.genScores ) ):
      s = self.genScores[0:i + 1]
      self.genScores[i].votes = i + 1
      self.genScores[i].score = sum( [v.vote for v in s] ) / len( s )

      self.genHist[int( self.genScores[i].vote ) - 1] += 1

    self.genHist = [int( h ) for h in self.genHist]




  def __init__( self, user, challengeID ):
    self.challengeID = challengeID
    self.genScores = []
    self.genHist = [0] * 10
    self.numDecremented = 0
    self.numIncremented = 0
    challenge = dbs.challengeTable.selectBy( user = user, challengeID = challengeID )[0]
    scores = dbs.voteTable.selectBy( challenge = challenge )
    self.scores = [dbs.voteVal( voteEntry = s ) for s in scores]
    self.last = dbs.voteVal();

    self.doInterpolation()


  def getScores( self ):
    return self.genScores

  def getHist( self ):
    return self.genHist






def main():
  dbs.validateDBs()
  scores = interpolate( 1548 ).getScores()
  #print [s.votes for s in scores]
  return 0

if __name__ == "__main__":
  main()


